Resumidamente, reatividade em programação é o conceito que torna possível a interação dinâmcica do usuário com o programa, no qual o que é efetivamente executado e exibido se baseia no acompanhamento das mudanças de determinados valores. Por exemplo, se um determinado input muda, um novo cálculo deve ser executado e um novo output gerado.
Programação Reativa
Como funciona a reatividade em apps Shiny?
A reatividade se baseia em uma paradigma diferente de programção, chamado de declarativo. No Shiny, declaramos dentro da função server() quando e quais códigos devem ser executados a depender de cada nova situação. As relações de dependência entre input e output e os consequentes fluxos de execução nesses casos são definidadas e representadas através de um diagrama de reatividade.
Para um app Shiny funcionar corretamente, é necessário que o diagrama de reatividade seja definido adequadamente na função server(). E para isso, alguns princípios devem ser observados. O primeiro deles é o seguinte: o diagrama de reatividade deve começar em um valor reativo e terminar em uma função observadora
Programação Reativa
Valores Reativos e Funções Observadoras
valores reativos são objetos que ativam a reatividade a partir das mudanças em seus valores. O principal exemplo de valor reativo são os próprios objetos do input.
funções observadoras são funções que acompanham as mudanças no valores reativos e executam algo diferente a partir delas. O principal exemplo de função reativas são as funções da famílias render*().
Programação Reativa
Expressões Reativas
Expressões Reativas são objetos especiais muito importantes que atuam como valor reativo e função observadora ao mesmo tempo. São utilizadas em situações onde um valor reativo utilizado dentro de uma função observadora depende outro valor reativo.
Programação Reativa
Expressões Reativas
Sua utilidade se torna mais claro quando levamos em consideração um segundo princípio importante da reatividade no shiny: valores e expressões reativas só podem ser lidas dentro de um contexto reativo.
Ou seja, em um caso onde precisemos criar uma variável que dependa de um input, mas que sirva para ativar a reatividade em outputs diferentes, precisamos de uma expressão reativa, por exemplo.
Programação Reativa
Expressões Reativas
exemplo:
Imagine uma aplicação Shiny que simule o lançar de um dado simples de 6 faces. Queremos que o usário insira o número de lançamentos (tamanho da amostra) desejado e que a partir desse número seja exibido um gráfico de barras com o quantidade de aparições de cada número (distribuição observada) e um frase informando qual valor mais apareceu.
Programação Reativa
Expressões Reativas
exemplo - primeira abordagem:
ui <-fluidPage("INCRÍVEL DADO",sliderInput(inputId ="tamanho",label ="Selecione o número de lançamentos",min =1,max =1000,value =500 ),plotOutput(outputId ="distribuicao"),textOutput(outputId ="frase"))
Programação Reativa
Expressões Reativas
exemplo - primeira abordagem:
server <-function(input, output, session) { lancamentos <-sample(1:6, input$tamanho, replace =TRUE) output$distribuicao <-renderPlot({ lancamentos |>table() |>barplot() }) output$frase <-renderText({ contagem <-table(lancamentos) mais_freq <-names(contagem[which.max(contagem)]) num_ap <- contagem[mais_freq]paste("o valor mais sorteado foi o", mais_freq, "com ", num_ap, "aparições") })}shinyApp(ui, server)
Programação Reativa
Expressões Reativas
Por que deu erro?
Justamente porque não seguimos o segundo princípio, e tentamos acessar o valor reativo input$tamanho dentro da variável comum lancamentos.
Qual é abordagem correta?
Podemos resolver criando o objeto lancamentos como uma expressão reativa através da função observadora reactive().
lancamentos <-reactive({sample(1:6, input$tamanho, replace =TRUE) })## Observação: devemos utilizar () ao lado do nome (como uma função)## para acessar as expressões reativas criadas
Programação Reativa
Funções Para Expressões Reativas
reactive()
A função reactive() cria uma expressão reativa que observa todos os valores reativos presentes dentro de seu código.
No exemplo anterior, criamos a expressão reativa lancamentos cujo valor é recalculado sempre que o valor reativo input$tamanho mudar, e utilizamos seu valor chamando lancamentos() dentro das funções observadoras renderPlot() e renderText().
Programação Reativa
Funções Para Expressões Reativas
eventReactive()
A função eventReactive() é similar, mas observa mudanças em apenas um valor reativo, especificado na chamada da própria função.
Geralmente é utilzada quando queremos atrasar (delay) a ativação da função observadora.
Um caso comum de uso é quando temos um botão na UI, criado com a função actionButton(), por exemplo.
Programação Reativa
Funções Para Expressões Reativas
eventReactive()
Podemos utilizar essa ideia para incrementar o nosso exemplo anterior, de tal forma que os outputs só serão gerados caso o botão seja clicado, independente se os valores de input$tamanho mudarem.
Adicionamos a função actionButton() da seguinte maneira:
actionButton(inputId ="botao", label ="Simular")
Programação Reativa
Funções Para Expressões Reativas
eventReactive()
E atribuímos ao objeto lancamentos dentro do server() a função eventReactive() tendo input$botao como primeiro argumento:
A funções observe() e observetEvent() tem o conceito semelhante a reactive() e eventReactive(), porém possuem uma diferença fundamental: elas não geram expressões reativas, sendo utilizadas apenas para rodar determinado código caso uma mudança em algum valor reativo aconteça. Ou seja, não podemos definir a expressão reativa lancamentos do exemplo anterior com elas.
Programação Reativa
Outras Funções Observadoras
observe() E observeEvent()
Geralmente são utilizadas quando queremos usar a reatividade para disparar (trigger) ações que não estão ligadas à geração de outputs, como o registro de informações em bases de dados ou o envio de e-mails, por exemplo.
Programação Reativa
Outras Funções Importantes
isolate()
Utilizada para isolar um valor reativo específico entre vários, de tal forma que se apenas ele for alterado nenhuma reatividade é disparada.
Programação Reativa
Outras Funções Importantes
reactiveVal() E reactiveValues()
Utilizada para gerar apenas um (reactiveVal) ou mais (reactiveValues) valores reativos mutáveis, diferentes do objetos do input, que são imutáveis.
Pode ser usada em alguns casos quando queremos controlar valores reativos dentro do server(), e renderizar mudanças na UI a partir deles.
Programação Reativa
Outras Funções Importantes
req() E validate()
Utilizada para validar valores reativos. Nesse contexto inválido indica um objeto:
• FALSE
• NULL
• "", uma string vazia
• Um vetor vazio
• Um vetor que contenha apenas NA
• Um vetor lógico que contenha apenas FALSE ou NA
• Um objeto com classe try-error
• Um valor reativo que represente um actionButton() que ainda não foi clicado
Programação Reativa
Outras Funções Importantes
req() E validate()
A função req() retorna um erro silencioso. Com o qual podemos definir que o server() e a ui() devem manter as coisas como estavam antes.
Já a função validate() permite customizar o erro retornado.